//
// Created by QU on 2023/8/16.
//

#include <stdio.h>
#include <memory.h>
#include <stdlib.h>

#include "VHDLSender.h"
#include "header.h"
#include "utils.h"
#include "dataGeneratorFiller.h"
#include "paramPasser.h"


bool VERBOSE_FLAG;

extern struct paramFlag paramFlag;


int main(int argc, char *argv[]) {
    VERBOSE_FLAG = false;

#ifdef TEST_MODE
    testUtils();
    testDataGenerator();
    testParamPasser(argc, argv);
#endif

    if (VERBOSE_FLAG) { printInfoMessage("Parsing to strParam..."); }
    struct strParameter strParameter = parameterPasserToStrParam(argc, argv);
    struct numParameter numParameter = parseStrParameterToNumParameter(paramFlag, strParameter);
    if (VERBOSE_FLAG) { printInfoMessage("Parsing to numParam..."); }

#ifdef DEBUG_PRINT_PARAMETER_CONTENT
    printDebugMessage("Parameter Content:");
    printNumParameter(&numParameter);
#endif

    if (paramFlag.structuremode == true) {
        if (multipleChannelGenerator(numParameter)) {
            printInfoMessage("multipleChannelGenerator generate complete.");
        } else
        {
            printErrorMessage("multipleChannelGenerator generate ERROR.");
        }
    } else {
        if (singleChannelGenerator(numParameter)){
            printInfoMessage("singleChannelGenerator generate complete.");
        } else {
            printErrorMessage("singleChannelGenerator generate ERROR.");
        }
    }

    return 0;
}

bool singleChannelGenerator(struct numParameter numParam) {
    if (paramFlag.structuremode != false && numParam.numStructureMode != 9999) {
        printErrorMessage("Structure mode ERROR.");
        exit(EXIT_FAILURE);
    }

    if (VERBOSE_FLAG) {
        printInfoMessage("singleChannelGenerator generating...");
    }


    size_t generateBufferLength = 0;
    if (paramFlag.genframenum == true && paramFlag.genlength == false) {
        generateBufferLength =
                getBufferLengthFromGenFrameNum(numParam.numGenFrameNum, numParam.numVCType) * numParam.numSplitedCols;
    } else if (paramFlag.genframenum == false && paramFlag.genlength == true) {
        generateBufferLength = numParam.numGenLength;
    } else {
        printErrorMessageWithExtraMessage("singleChannelGenerator getBufferLength ERROR", "Aborting...");
    }

    if (VERBOSE_FLAG) {
        printInfoMessage("generateBufferLength get Success.");
        printf("generateBufferLength: %zu\n", generateBufferLength);
    }

    // malloc data block
    uint8_t *generateBuffer = malloc(generateBufferLength);
    if (generateBuffer == NULL) {
        printErrorMessage("malloc generateBufferLength failed");
        exit(EXIT_FAILURE);
    } else {
        if (VERBOSE_FLAG) {
            printInfoMessage("malloc generateBufferLength success");
        }
    }

    // fill generateData to generateBuffer.
    switch (numParam.numGenDataType) {
        case FIXED_60A1DA8E:
            if (VERBOSE_FLAG) {
                printInfoMessage("generate type: FIXED_60A1DA8E (0)");
            }
            if (generateBufferLength !=
                generateData_60a1da8e(generateBuffer, generateBufferLength, generateBufferLength)) {
                printWarningMessageWithExtraMessage("generateDate Runtime Warning:", "May NOT Totally Filled");
            }
            break;
        case FIXED_LowerINC_HigherLOID:
            if (VERBOSE_FLAG) {
                printInfoMessage("generate type: FIXED_LowerINC_HigherLOID (1)");
            }
            if (generateBufferLength !=
                generateData_LowerIncrementHigherLogicalID(generateBuffer, generateBufferLength, generateBufferLength,
                                                           numParam.numLogicalID)) {
                printWarningMessageWithExtraMessage("generateDate Runtime Warning:", "May NOT Totally Filled");
            }
            break;
        case FIXED_LogicINC:
            if (VERBOSE_FLAG) {
                printInfoMessage("generate type: FIXED_LogicINC (2)");
            }
            if (generateBufferLength !=
                generateData_ChannelIncrement(generateBuffer, generateBufferLength, generateBufferLength,
                                              numParam.numLogicalID)) {
                printWarningMessageWithExtraMessage("generateDate Runtime Warning:", "May NOT Totally Filled");
            }
            break;
        case FIXED_00TOFF:
            if (VERBOSE_FLAG) {
                printInfoMessage("generate type: FIXED_00TOFF (3)");
            }
            if (generateBufferLength !=
                generateData_00toFF(generateBuffer, generateBufferLength, generateBufferLength)) {
                printWarningMessageWithExtraMessage("generateDate Runtime Warning:", "May NOT Totally Filled");
            }
            break;
        case INPUTFILE:
            if (VERBOSE_FLAG) {
                printInfoMessage("generate type: INPUTFILE (INPUTFILE)");
            }
            printWarningMessage("INPUTFILE not support now!");
            break;
    }
    if (VERBOSE_FLAG) {
        printInfoMessage("generateData to generateBuffer Complete!");
    }

#ifdef DEBUG_PRINT_BUFFER_CONTENT
    printDebugMessage("print generateBuffer Content:");
    printBufferDataContent(generateBuffer, generateBufferLength);
#endif

    size_t outputBufferLength = getTotalFullLengthFormBufferLength(generateBufferLength, numParam.numVCType,
                                                                   numParam.numSplitedCols);
    size_t outputBufferOnelineLength = getTotalFullLengthOneLineFromBufferLength(generateBufferLength,
                                                                                 numParam.numVCType,
                                                                                 numParam.numSplitedCols);

    uint8_t *outputBuffer = malloc(outputBufferLength);
    if (outputBuffer == NULL) {
        printErrorMessage("malloc outputBuffer failed");
        return false;
    } else {
        if (VERBOSE_FLAG) {
            printInfoMessage("malloc outputBuffer success");
        }
    }

    // prepare for header
    vcTypeHeader_t genHeader = {0};

    generateHeader(&genHeader, numParam.numVCType, numParam.numLogicalID, numParam.numPhysicalID, 0, 0, 0);

#ifdef DEBUG_PRINT_HEADER_CONTENT
    printDebugMessage("Preparing starter vcHeader, Content:");
    printVCTypeHeader(&genHeader);
#endif

    size_t filledLoadLength = outputBufferLoadFiller(generateBuffer, generateBufferLength, numParam.numVCType,
                                                     numParam.numSplitedCols, outputBufferOnelineLength,
                                                     (void *) outputBuffer);
    size_t filledHeaderLength = outputBufferHeaderFiller(genHeader, numParam.numVCType, numParam.numSplitedCols,
                                                         outputBufferOnelineLength, (void *) outputBuffer);
    size_t filledMFILength = outputBufferMFIFiller(numParam.numVCType, numParam.numSplitedCols,
                                                   outputBufferOnelineLength, (void *) outputBuffer,
                                                   numParam.numStartMFI);
    if (VERBOSE_FLAG) {
        printInfoMessage("outputBuffer Filled!");
    }

#ifdef DEBUG_PRINT_OUTBUFFER_CONTENT
    printDebugMessage("print OutputBuffer Content:");
    printOutputBufferContent(numParam.numVCType, numParam.numSplitedCols, outputBufferOnelineLength,
                             (void *) outputBuffer);
#endif

    if (VERBOSE_FLAG) {
        printf("total filled size: %zu\n", filledHeaderLength + filledLoadLength + filledMFILength);
    }

    // output to file:
    if (outputToFiles(numParam.numSplitedCols, outputBufferOnelineLength, (void *) outputBuffer,
                      numParam.numPhysicalID)) {
        if (VERBOSE_FLAG) {
            printInfoMessage("output to file complete");
        }
    } else {
        printErrorMessage("output to file ERROR");
        return false;
    }

    // free buffer
    free(outputBuffer);
    if (VERBOSE_FLAG) {
        printInfoMessage("free outputBuffer success");
    }

    free(generateBuffer);
    if (VERBOSE_FLAG) {
        printInfoMessage("free generateBuffer success");
    }

    if (VERBOSE_FLAG) {
        printInfoMessage("singleChannelGenerator generate complete.\n");
    }
    return true;

}

bool multipleChannelGenerator(struct numParameter numParam) {
    if (paramFlag.structuremode == false || numParam.numStructureMode == 9999) {
        printErrorMessage("Structure mode ERROR.");
    }

    printInfoMessage("multipleChannelGenerator generating...");

    struct numParameter tempParam = {0};

    switch (numParam.numStructureMode) {
// 0~255：全 VC-4 模式（10G SDH 中包含 64 个 VC-4）
//0:  全 VC-4 模式，每个 VC-4 为一个单独的逻辑通道
        case 0:
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 1;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numGenLength = numParam.numGenLength;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }


            for (int i = 0; i < 64; ++i) {
                if (singleChannelGenerator(tempParam)) {
                    tempParam.numLogicalID++;
                    tempParam.numPhysicalID++;
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
            }

            break;

//1：全 VC-4 模式，64 个 VC-4 组合成 1 个逻辑通道
        case 1:
            // -S 1 --gentype 00toff --genframenum 640 --startphysicalid 0 --startlogicalid 0 --startmfi 100
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 64;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numGenLength = numParam.numGenLength;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            if (singleChannelGenerator(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }
            break;
//2：全 VC-4 模式，32 个 VC-4 组合成 1 个逻辑通道，其它每个 VC-4 为独立的逻辑通道
        case 2:
            //  -S 2 --gentype 00toff --genframenum 320 --startphysicalid 0 --startlogicalid 0 --startmfi 100
            // 32个逻辑1
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 32;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numGenLength = numParam.numGenLength;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            if (singleChannelGenerator(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }

            tempParam.numPhysicalID += 32;
            tempParam.numLogicalID++;

            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 1;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numGenLength = numParam.numGenLength;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            for (int i = 0; i < 32; ++i) {
                if (singleChannelGenerator(tempParam)) {
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
                tempParam.numLogicalID++;
                tempParam.numPhysicalID++;
            }

            break;



//256~511：全 VC-12 模式（10G SDH 中包含 4032 个 VC-4）
//256:  全 VC-12 模式，每个 VC-12 为一个单独的逻辑通道
        case 256:
            //  -S 256 --gentype 00toff --genframenum 30 --startphysicalid 0 --startlogicalid 0 --startmfi 100  > mode256_output.txt
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 1;
            tempParam.numVCType = VC_12;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numGenLength = numParam.numGenLength;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            for (int i = 0; i < 4032; ++i) {
                if (singleChannelGenerator(tempParam)) {
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
                tempParam.numLogicalID++;
                tempParam.numPhysicalID++;
            }


            break;
//257：全 VC-12 模式，每 64 个 VC-12 组合成 1 个逻辑通道（需注意 VC-12-Xv， X 的值最大为 64），共 63 个逻辑通道。
        case 257:
            //  -S 257 --gentype 00toff --genframenum 640 --startphysicalid 0 --startlogicalid 0 --startmfi 100  > mode257_output.txt
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 64;
            tempParam.numVCType = VC_12;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numGenLength = numParam.numGenLength;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            for (int i = 0; i < 63; ++i) {
                if (singleChannelGenerator(tempParam)) {
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
                tempParam.numPhysicalID += 64;
                tempParam.numLogicalID++;
            }


            break;
//512~767：VC-4/VC-12 混合模式
//512：63 个 VC-4，63 个 VC-12；63 个 VC-4 组成 1 个逻辑通道，63 个 VC-12 组成 1 个逻辑通道。
        case 512:
            // --structuremode 512 --gentype 00toff --genframenum 126 --startphysicalid 0 --startlogicalid 0 --startmfi 100

            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 63;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numGenLength = numParam.numGenLength;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            if (singleChannelGenerator(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }

            tempParam.numPhysicalID += 63;
            tempParam.numLogicalID++;

            ////////
            tempParam.numSplitedCols = 63;
            tempParam.numVCType = VC_12;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }
            if (singleChannelGenerator(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }


            break;

//我们暂时只以上产生 6 种通道结构，并用 STRUCTURE_MODE 参数为 0、1、2、 256、257、512 分别表示这 6 种结构。

        default:
            printf("Unknown STRUCTURE_MODE value...\n");
            exit(EXIT_FAILURE);
    }

    return true;
}
